package com.bj58.mis.apm.server.statistics.service.impl;

import com.alibaba.druid.sql.SQLUtils;
import com.bj58.mis.apm.server.core.common.result.Page;
import com.bj58.mis.apm.server.core.common.result.SimplePage;
import com.bj58.mis.apm.server.core.util.ParameterUtils;
import com.bj58.mis.apm.server.statistics.dto.chart.ChartData;
import com.bj58.mis.apm.server.statistics.dto.chart.ValueBean;
import com.bj58.mis.apm.server.statistics.dto.query.QueryDataGridItem;
import com.bj58.mis.apm.server.statistics.dto.query.QueryPercentile;
import com.bj58.mis.apm.server.statistics.dto.query.Statistics;
import com.bj58.mis.apm.server.statistics.mapper.QueryMapper;
import com.bj58.mis.apm.server.statistics.service.BaseService;
import com.bj58.mis.apm.server.statistics.service.QueryService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class QueryServiceImpl extends BaseService<QueryMapper> implements QueryService {
    /**
     * 根据用户名,项目ID和cubeId 获取有权限的Cube ID列表
     *
     * @param username  用户名
     * @param projectId 项目ID
     * @param cubeId    cubeId
     * @return
     */
    private List<String> getCubeIdList(String username, String projectId, String cubeId) {
        List<String> cubeIdList = null;

        if (cubeId != null && !"".equals(cubeId)) {
            //指定cubeId
            cubeIdList = new ArrayList<String>();
            cubeIdList.add(cubeId);
        } else if(!isAdmin(username)) {
            cubeIdList = this.getAuthCubeIdList(username, projectId);
        }else if(isAdmin(username)&&projectId!=null&&projectId!=""){
            cubeIdList=this.mapper.getProjectList(projectId);
        }
        if (cubeIdList == null || cubeIdList.size() == 0) {
            return null;
        }

        return cubeIdList;
    }

    /**
     * 查询统计信息
     *
     * @param username  用户名称
     * @param projectId 项目ID
     * @param cubeId    cubeId
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return
     */
    public Statistics statistics(String username, String projectId, String cubeId, String startDate, String endDate) {
        List<String> cubeIdList = getCubeIdList(username, projectId, cubeId);
        if (cubeIdList == null && !super.isAdmin(username)) {
            return new Statistics();
        }
        Statistics s = this.mapper.getStatisticsByHiveResult(cubeIdList, startDate, endDate);

        return s == null ? new Statistics() : s;
    }

    /**
     * 获取每天的查询次数
     *
     * @param username  用户名
     * @param projectId 项目ID
     * @param cubeId    cubeID
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return
     */
    public ChartData queryCount(String username, String projectId, String cubeId, String startDate, String endDate) {
        List<String> cubeIdList = getCubeIdList(username, projectId, cubeId);
        if (cubeIdList == null && !super.isAdmin(username)) {
            return new ChartData();
        }
        List<Map<String, ?>> resultList = this.mapper.getQueryCountByHiveResult(cubeIdList, startDate, endDate);
        ChartData chartData = ChartData.buildChartData(resultList, "dt", new String[]{"value"});
        chartData.calc();
        for(ValueBean vb:chartData.getValueBeans()){
            vb.setName("查询次数");
            vb.setUnit("次");
        }
        return chartData;
    }

    /**
     * 获取查询时间相应的分布
     *
     * @param username  用户名
     * @param projectId 项目ID
     * @param cubeId    cubeId
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return
     */
    public ChartData queryTimeData(String username, String projectId, String cubeId, String startDate, String endDate) {
        List<String> cubeIdList = this.getCubeIdList(username, projectId, cubeId);
        if (cubeIdList == null && !super.isAdmin(username)) {
            return new ChartData();
        }
        List<Map<String, ?>> resultList = this.mapper.queryTimeDataByHiveResult(cubeIdList, startDate, endDate);
        ChartData chartData = ChartData.buildChartData(resultList, "dictionary_item_key", new String[]{"value"});
        chartData.calc();
        for(ValueBean vb:chartData.getValueBeans()){
            vb.setName("查询相应时间分布");
            vb.setUnit("s");
        }
        return chartData;
    }

    /**
     * 获取历史查询的时间和耗时
     *
     * @param md5       sql和cubeId联合计算的MD5值
     * @param state     状态.1表示成功执行的SQL;0表示执行失败的SQL
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return
     */
    public ChartData queryHistory(String md5, String state, String startDate, String endDate) {
        List<Map<String, ?>> resultList = this.mapper.queryHistory(md5, state, startDate, endDate);
        ChartData chartData = ChartData.buildChartData(resultList, "query_time", new String[]{"duration"});

        for(ValueBean vb:chartData.getValueBeans()){
            vb.setName("查询历史");
            vb.setUnit("s");
        }
        return chartData;
    }

    /**
     * 获取查询列表中某条记录的信息
     *
     * @param md5       sql和cubeId联合计算的MD5值
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return
     */
    public QueryDataGridItem queryDataGridItem(String md5, String startDate, String endDate,String state) {
        QueryDataGridItem item = this.mapper.getOneQueryLog(md5, startDate, endDate,state);
        if(item != null && StringUtils.isNotEmpty(item.getSql())) {
            item.setSql(SQLUtils.formatMySql(item.getSql()));
        }
        return item;
    }

    /**
     * 查询列表
     *
     * @param username  用户名
     * @param projectId 项目ID
     * @param cubeId    cubeId
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @param user      负责人
     * @param state     状态.1表示成功执行的SQL;0表示执行失败的SQL
     * @param searchKey 搜索的内容.可以是项目名称,也可以是cube名称
     * @param orderBy   排序的字段
     * @param sort      排序的方向。asc或者是desc
     * @param page      分页的偏移量
     * @param limit     每页的记录数
     * @return
     */
    public Page<QueryDataGridItem> queryDataGrid(String username, String projectId, String cubeId, String startDate, String endDate, String user, String state, String searchKey, String orderBy, String sort, Integer page, Integer limit) {
        List<String> cubeIdList = getCubeIdList(user != null && !"".equals(user) ? user : username, projectId, cubeId);
        if (cubeIdList == null && !super.isAdmin(username)) {
            return new SimplePage<QueryDataGridItem>(0, new ArrayList<QueryDataGridItem>());
        }
        //如果管理员选择了负责人,则需要查询负责人的权限
        if(user!=null && !"".equals(user)){
            cubeIdList=this.getAuthCubeIdList(user, projectId);
            cubeIdList.add(" ");
        }
        int offset = (page - 1) * limit;
        offset = offset < 0 ? 0 : offset;
        searchKey=ParameterUtils.getBLikeValue(searchKey);

        List<QueryDataGridItem> resultList = this.mapper.queryDataGridByHiveResult(cubeIdList, startDate, endDate, user, state, searchKey, orderBy, sort, offset, limit);
        Integer totalRecord = this.mapper.queryDataGridCountByHiveResult(cubeIdList, startDate, endDate, user, state, searchKey);
        SimplePage s= new SimplePage<QueryDataGridItem>(totalRecord == null ? 0 : totalRecord, resultList == null ? new ArrayList<QueryDataGridItem>() : resultList);
        s.setLimit(limit);
        s.setPage(page);
        return s;
    }

    /**
     * 查询每天的百分位数
     *
     * @param username  用户名
     * @param projectId 项目ID
     * @param cubeId    cubeId
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return
     */
    public ChartData queryPercentile(String username, String projectId, String cubeId, String startDate, String endDate) {
        List<String> cubeIdList = getCubeIdList(username, projectId, cubeId);
        if (cubeIdList == null && !super.isAdmin(username)) {
            return new ChartData();
        }
        /**
         * 普通用户,没有选择项目和cube.则在权限所辖的cube列表中,选择最后构建的cube作为查询的内容
         */
        if((cubeId==null || cubeId=="") && (projectId==null||projectId=="") && !super.isAdmin(username)){
            cubeIdList=this.mapper.getLastBuildCube(cubeIdList);
        }
        ChartData chartData = new ChartData();
        List<QueryPercentile> resultList = this.mapper.queryPercentileByHiveResult(projectId,cubeId,cubeIdList, startDate, endDate);

        chartData.setCategory(new ArrayList<String>());
        chartData.setValueBeans(new ArrayList<ValueBean>());
        for (QueryPercentile q : resultList) {
            if (!chartData.getCategory().contains(q.getQueryTime())) {
                chartData.getCategory().add(q.getQueryTime());
            }

            ValueBean vb = null;

            for (ValueBean v : chartData.getValueBeans()) {
                if (v.getName().equals(q.getName())) {
                    v.getData().add(q.getDuration());
                    vb = v;
                }
            }
            if (vb == null) {
                vb = new ValueBean();
                vb.setData(new ArrayList<Double>());
                vb.setName(q.getName());
                vb.setSubName(q.getSubname());
                vb.setUnit("s");
                vb.getData().add(q.getDuration());
                chartData.getValueBeans().add(vb);
            }
        }


        return chartData;
    }
}
